use crate::error::{Error, Result};

pub fn write_varint(buf: &mut Vec<u8>, mut value: u64) {
    loop {
        let mut byte = (value & 0x7F) as u8;
        value >>= 7;
        if value != 0 {
            byte |= 0x80;
        }
        buf.push(byte);
        if value == 0 {
            break;
        }
    }
}

pub fn read_varint(data: &[u8]) -> Result<(u64, usize)> {
    let mut value = 0u64;
    let mut shift = 0;
    let mut bytes_read = 0;

    for &byte in data {
        bytes_read += 1;
        value |= ((byte & 0x7F) as u64) << shift;

        if byte & 0x80 == 0 {
            return Ok((value, bytes_read));
        }

        shift += 7;
        if shift >= 64 {
            return Err(Error::VarintOverflow);
        }
    }

    Err(Error::IncompleteVarint)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_varint_roundtrip() {
        let values = vec![0, 1, 127, 128, 255, 256, 65535, 1000000];
        
        for value in values {
            let mut buf = Vec::new();
            write_varint(&mut buf, value);
            let (decoded, _) = read_varint(&buf).unwrap();
            assert_eq!(decoded, value);
        }
    }
}
